<?php
/**
 * Created by PhpStorm.
 * User: Hong
 * Date: 2018/4/2
 * Time: 9:44
 * Function:
 */

namespace App\Http\Middleware;


use Illuminate\Container\Container as App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Platform\Models\Admin\Administrator;
use Platform\Models\Admin\OperationLog as AdminOperationLog;

class OperationLog
{

    /**
     * @var App
     */
    private $app;

    /**
     * @var array
     */
    private $config;

    /**
     * @var Model
     */
    protected $operation_model;

    /**
     * @var Model
     */
    protected $user_model;

    /**
     * OperationLog constructor.
     */
    public function __construct()
    {
        $this->config = config('system.operation_log.admin');
    }

    /**
     * 创建模型对象
     * @return Model|mixed
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function makeModel() {

        $this->app = new App();

        $this->user_model = $this->app->make($this->config['user_model']);
        if (!$this->user_model instanceof Model){
            myResult()->stop(500,"Class {$this->config['user_model']} must be an instance of Illuminate\\Database\\Eloquent\\Model");
        }

        $this->operation_model = $this->app->make($this->config['operation_log_model']);
        if (!$this->operation_model instanceof Model){
            myResult()->stop(500,"Class {$this->config['operation_log_model']} must be an instance of Illuminate\\Database\\Eloquent\\Model");
        }

    }

    /**
     * @param Request $request
     * @param \Closure $next
     * @param $auth_type
     * @return mixed
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function handle(Request $request, \Closure $next, $auth_type)
    {
        $this->config = config('system.operation_log.'.$auth_type);

        $this->makeModel();

        if ($this->needToLog($request)) {
            $make_data_function = $auth_type.'LogData';
            $log = call_user_func(array($this, $make_data_function),$request);

            $this->operation_model::create($log);
        }

        return $next($request);
    }

    protected function adminLogData(Request $request){
        return [
            'admin_id' => $this->user_model::user()->id,
            'path'     => $request->path(),
            'method'   => $request->method(),
            'ip'       => $request->getClientIp(),
            'input'    => json_encode($request->input()),
        ];
    }

    protected function organizeLogData(Request $request){
        return [
            'leader_id' => $this->user_model::user()->id,
            'organize_id' => $this->user_model::user()->organize->id,
            'path'     => $request->path(),
            'method'   => $request->method(),
            'ip'       => $request->getClientIp(),
            'input'    => json_encode($request->input()),
        ];
    }

    /**
     * @param Request $request
     *
     * @return bool
     */
    protected function needToLog(Request $request)
    {
        return $this->config['enable']
            && !$this->inExceptArray($request)
            && $this->user_model::user();
    }

    /**
     * Determine if the request has a URI that should pass through CSRF verification.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return bool
     */
    protected function inExceptArray($request)
    {
        foreach ($this->config['except'] as $except) {
            if ($except !== '/') {
                $except = trim($except, '/');
            }

            $methods = [];

            if (Str::contains($except, ':')) {
                list($methods, $except) = explode(':', $except);
                $methods = explode(',', $methods);
            }

            $methods = array_map('strtoupper', $methods);

            if ($request->is($except) &&
                (empty($methods) || in_array($request->method(), $methods))) {
                return true;
            }
        }

        return false;
    }
}